Skip to content

feat: add Teams (Circles) async API#403

Merged
oleksandr-nc merged 6 commits intomainfrom
feat/teams-circles-api
Mar 24, 2026
Merged

feat: add Teams (Circles) async API#403
oleksandr-nc merged 6 commits intomainfrom
feat/teams-circles-api

Conversation

@bigcat88
Copy link
Contributor

@bigcat88 bigcat88 commented Feb 19, 2026

Summary

Closes #343

  • Adds async-only _AsyncTeamsAPI module (nc_py_api/teams.py) for managing Nextcloud Teams (Circles)
  • Full CRUD: create, get_list, get_details, destroy, edit_name, edit_description, edit_config
  • Member management: add_member, add_members, remove_member, set_member_level, confirm_member, join, leave
  • Data classes: Circle, Member with typed properties
  • Enums: MemberType, MemberLevel, CircleConfig (IntFlag)
  • Registered on _AsyncNextcloudBasic — available on both AsyncNextcloud and AsyncNextcloudApp

Following the async-only policy for new features — no sync variant.

Test plan

  • 17 async tests in tests/actual_tests/teams_test.py
  • test_teams_available and test_teams_create_destroy run in both client and AppAPI modes (anc fixture)
  • Circle CRUD: create, get_list, get_details, destroy, edit_name, edit_description, edit_config
  • Member lifecycle: add_member, add_members (multi), remove_member, set_member_level
  • Join/leave open circle flow
  • Personal and local circle creation
  • Error handling: destroy nonexistent circle raises NextcloudException
  • Full suite: 613 passed, 6 skipped, 0 failures

Summary by CodeRabbit

  • New Features

    • Added Teams (Circles) API: create, list, edit, delete teams; manage membership and roles; join/leave flows.
    • Exposed Teams-related types on the package public API.
  • Tests

    • Added comprehensive async integration tests covering lifecycle, membership, role changes, join/request/confirm flows, and config flags.
  • Chores

    • CI workflow updated to enable and configure the Circles app during test matrix runs.

@bigcat88 bigcat88 changed the title feat: add Teams (Circles) async API feat: add Teams (Circles) async API [TEST PR] Feb 19, 2026
@oleksandr-nc oleksandr-nc added this to the 1.0.0 milestone Feb 19, 2026
@bigcat88 bigcat88 modified the milestones: 1.0.0, 0.30.0 Mar 5, 2026
bigcat88 and others added 3 commits March 24, 2026 06:46
Implements issue #343 — adds async-only Teams/Circles API to nc_py_api.

New module `nc_py_api/teams.py` provides:
- Data classes: Circle, Member
- Enums: MemberType, MemberLevel, CircleConfig
- _AsyncTeamsAPI with methods: available, get_list, create, get_details,
  destroy, edit_name, edit_description, edit_config, get_members,
  add_member, add_members, remove_member, set_member_level,
  confirm_member, join, leave

Registered on _AsyncNextcloudBasic (AsyncNextcloud + AsyncNextcloudApp).
17 tests covering both client and AppAPI modes.
Fix add_member, confirm_member to return Member (API returns single
dict, not list). Fix remove_member to return None (API returns empty
array). Accept CircleConfig | int in edit_config. Export public classes
from __init__.py. Fix hardcoded URL in tests, revert unrelated
gfixture_set_env change.
@bigcat88 bigcat88 force-pushed the feat/teams-circles-api branch from 7afd3a8 to cf167e6 Compare March 24, 2026 06:46
@coderabbitai
Copy link

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

Adds async Nextcloud Teams (Circles) support: new nc_py_api/teams.py module with typed models and _AsyncTeamsAPI, exposes types at package root, hooks teams into the async client, adds integration tests, and updates CI to install/enable the Circles app for tests.

Changes

Cohort / File(s) Summary
CI / Workflow
.github/workflows/analysis-coverage.yml
Checks out nextcloud/circles into apps/circles, enables the Circles app in test jobs, and sets overwrite.cli.url during Nextcloud setup for tests-maria and tests-pgsql.
Package exports
nc_py_api/__init__.py
Added top-level exports: Circle, CircleConfig, Member, MemberLevel, MemberType (re-exported from .teams).
Client integration
nc_py_api/nextcloud.py
Async client _AsyncNextcloudBasic now declares and initializes teams: _AsyncTeamsAPI for Teams/Circles operations.
Teams API implementation
nc_py_api/teams.py
New module implementing Teams/Circles: MemberType, MemberLevel, CircleConfig, Member and Circle dataclasses, and _AsyncTeamsAPI with async methods for availability, list/create/get/edit/destroy circles, membership management (add/remove/bulk, set level, confirm), and join/leave flows.
Integration tests
tests/actual_tests/teams_test.py
New async pytest suite exercising circle lifecycle, edits, config flags, member add/remove/bulk/level/confirm, join/leave flows, personal/local variants, and error cases; gated on teams.available.

Sequence Diagram(s)

sequenceDiagram
    participant Test as rgba(0,128,255,0.5) Test Suite
    participant Client as rgba(0,200,100,0.5) AsyncNextcloud (anc)
    participant Server as rgba(255,100,0,0.5) Nextcloud OCS API
    participant UserClient as rgba(150,50,200,0.5) AsyncNextcloud (test user)

    Test->>Client: anc.teams.create(name, personal?, local?)
    Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles (body)
    Server-->>Client: 201 Created + circle payload
    Client-->>Test: Circle object

    Test->>Client: anc.teams.add_member(circle_id, user_id)
    Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/members
    Server-->>Client: 200 OK + member payload
    Client-->>Test: Member object

    Test->>UserClient: user.teams.join(circle_id)
    UserClient->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/join
    Server-->>UserClient: 200 OK (or pending request)
    UserClient-->>Test: Circle / Member status

    Test->>Client: anc.teams.confirm_member(circle_id, member_id)
    Client->>Server: POST /ocs/v2.php/apps/circles/api/v1/circles/{id}/members/{mid}/confirm
    Server-->>Client: 200 OK + updated member
    Client-->>Test: Confirmed Member object
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding async API support for Teams (Circles) functionality, which aligns with the primary objective of implementing circle/team management.
Linked Issues check ✅ Passed The PR fully implements the coding requirements from issue #343: programmatic circle management (CRUD operations), member lifecycle management (add/remove/confirm), and exposes Circles app endpoints via _AsyncTeamsAPI.
Out of Scope Changes check ✅ Passed All changes are scoped to Teams/Circles implementation. The workflow modifications (enabling Circles app in CI) and package exports are necessary supporting changes directly related to the feature.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/teams-circles-api

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Review added 2 commits March 24, 2026 07:04
Add pytest.skip("Teams (Circles) is not installed") guard to every
teams test, matching the pattern used by notes/activity/talk tests.

Install circles app in tests-pgsql and tests-maria CI jobs so tests
actually run on those pipelines, while gracefully skipping on others.
The Circles app processes member removal and join operations
asynchronously via HTTP loopback. Without overwrite.cli.url configured,
the loopback fails silently and these operations never complete.

Also enable circles after the PHP server starts so the app can verify
its loopback connectivity at initialization time.
@codecov
Copy link

codecov bot commented Mar 24, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.69%. Comparing base (b202bd4) to head (1e0f246).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #403      +/-   ##
==========================================
+ Coverage   94.47%   94.69%   +0.21%     
==========================================
  Files          46       47       +1     
  Lines        5359     5575     +216     
==========================================
+ Hits         5063     5279     +216     
  Misses        296      296              
Files with missing lines Coverage Δ
nc_py_api/__init__.py 100.00% <100.00%> (ø)
nc_py_api/nextcloud.py 94.85% <100.00%> (+0.06%) ⬆️
nc_py_api/teams.py 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bigcat88 bigcat88 marked this pull request as ready for review March 24, 2026 07:42
@bigcat88 bigcat88 changed the title feat: add Teams (Circles) async API [TEST PR] feat: add Teams (Circles) async API Mar 24, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/analysis-coverage.yml:
- Around line 416-417: Add the Circles checkout and enablement to the
tests-client-sqlite job so client-mode Teams tests run under Circles as in
tests-maria/tests-pgsql: ensure the workflow job named tests-client-sqlite
includes the same checkout step for the Circles app and the "Enable Circles"
step that runs the command php occ app:enable circles (same as the existing
Enable Circles step in the diff), mirroring the setup used in
tests-maria/tests-pgsql; also consider doing the same for tests-oci if you want
OCI client-mode coverage.

In `@nc_py_api/teams.py`:
- Around line 114-122: The user_type and level properties currently call
MemberType(self._raw_data.get("userType", 1)) and
MemberLevel(self._raw_data.get("level", 0)) which will raise ValueError if the
API returns unknown enums; update these accessors (user_type and level) to
defensively handle invalid values by catching ValueError (or using the
Enum._missing_ hook) and returning a safe fallback (e.g., MemberType.USER and
MemberLevel.NONE) while still using self._raw_data.get(...) to obtain the raw
value; ensure the change references the same symbols (user_type, level,
MemberType, MemberLevel, and _raw_data) so behavior is forward-compatible with
unexpected API values.
- Around line 138-143: The `@dataclasses.dataclass` decorator on class Circle is
unnecessary because Circle defines a custom __init__ and doesn't use dataclass
features; remove the decorator line above class Circle (and mirror the same
removal you applied to Member) so Circle is a plain class with its existing
__init__ and _raw_data attribute.
- Around line 87-92: The `@dataclasses.dataclass` decorator on class Member is
misleading because Member defines a custom __init__ (and __repr__), so remove
the decorator line from the class definition and keep the existing
__init__/_raw_data handling (or alternatively, if you prefer using dataclass
semantics, replace the custom __init__ and __repr__ with dataclass field
declarations such as raw_data: dict and let dataclass generate
__init__/__repr__); in short, either delete the `@dataclasses.dataclass` decorator
from Member or refactor Member to declare dataclass fields and remove the manual
__init__/__repr__ so the decorator is used correctly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 84095ae1-ec9c-442b-9476-282d80a6c9c2

📥 Commits

Reviewing files that changed from the base of the PR and between b202bd4 and 4b6050b.

📒 Files selected for processing (5)
  • .github/workflows/analysis-coverage.yml
  • nc_py_api/__init__.py
  • nc_py_api/nextcloud.py
  • nc_py_api/teams.py
  • tests/actual_tests/teams_test.py

Tests the full request-to-join flow: create circle with REQUEST config,
user requests to join (status=Requesting), admin confirms the member
(status=Member).
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/actual_tests/teams_test.py`:
- Line 121: The assertion currently hardcodes details.owner.user_id == "admin";
replace the hardcoded string with the test's actual acting-user id variable so
the check is environment-agnostic (e.g., assert details.owner.user_id ==
acting_user.user_id or assert details.owner.user_id == current_user.user_id —
locate the variable used in this test that represents the requester/test user
and use that instead of "admin").
- Around line 243-260: AsyncNextcloud instances (anc_user and anc_any) leak HTTP
connection pools because AsyncNextcloud provides no public close API; update the
test to explicitly close the underlying session adapters after using
AsyncNextcloud: wrap the operations that call anc_user.teams.join /
anc_user.teams.leave and anc_any.teams.get_members in try/finally blocks and in
the finally await closing of anc_user._session.adapter and
anc_user._session.adapter_dav (and do the same for anc_any) to ensure adapters
are closed and connections cleaned up.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 91a86c2e-1479-48b1-8406-3c091ea8f5d9

📥 Commits

Reviewing files that changed from the base of the PR and between 4b6050b and 1e0f246.

📒 Files selected for processing (1)
  • tests/actual_tests/teams_test.py

Copy link
Contributor

@oleksandr-nc oleksandr-nc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go!

@oleksandr-nc oleksandr-nc merged commit ef519ae into main Mar 24, 2026
37 checks passed
@oleksandr-nc oleksandr-nc deleted the feat/teams-circles-api branch March 24, 2026 08:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Teams management (formerly known as circles)

2 participants